//
// RS Game Framework
// Copyright © 2009 Jedd Haberstro
// jhaberstro@gmail.com
// 
// $Id:
//

#ifndef RS_PORTABILITY_GENERIC_ATOMIC_IPP
#define RS_PORTABILITY_GENERIC_ATOMIC_IPP

#ifndef RS_ATOMIC_IMPLEMENTATION_GUARD
#   error "Do not include this file directly! Instead include rs/Atomic.hpp"
#endif

namespace rs
{
	inline void Atomic::MemoryBarrier() { }
	
	inline void Atomic::ReadBarrier() { }
	
	inline void Atomic::WriteBarrier() { }
	
	inline void Atomic::CompilerBarrier() { }
	
    inline Int32 Atomic::AddFetch(Int32 volatile* address, Int32 value) {
        *address += value;
        return *address;
    }
    
    inline UInt32 Atomic::AddFetch(UInt32 volatile* address, UInt32 value) {
        *address += value;
        return *address;
    }
    
    inline Int32 Atomic::AndFetch(Int32 volatile* address, Int32 value) {
        *address &= value;
        return *address;
    }
    
    inline UInt32 Atomic::AndFetch(UInt32 volatile* address, UInt32 value) {
        *address &= value;
        return *address;
    }
    
    inline Int32 Atomic::OrFetch(Int32 volatile* address, Int32 value) {
        *address |= value;
        return *address;
    }
    
    inline UInt32 Atomic::OrFetch(UInt32 volatile* address, UInt32 value) {
        *address |= value;
        return *address;
    }
    
    inline Int32 Atomic::XorFetch(Int32 volatile* address, Int32 value) {
        *address ^= value;
        return *address;
    }
    
    inline UInt32 Atomic::XorFetch(UInt32 volatile* address, UInt32 value) {
        *address ^= value;
        return *address;
    }
    
    inline Boolean Atomic::CompareSwap(Int32 volatile* address, Int32 oldValue, Int32 newValue) {
        if (*address == oldValue) {
            *address = newValue;
            return true;
        }
        
        return false;
    }

    inline Boolean Atomic::CompareSwap(UInt32 volatile* address, UInt32 oldValue, UInt32 newValue) {
        if (*address == oldValue) {
            *address = newValue;
            return true;
        }
        
        return false;
    }
    
    inline Boolean Atomic::CompareSwap(void* volatile* address, void* oldValue, void* newValue) {
        if (*address == oldValue) {
            *address = newValue;
            return true;
        }
        
        return false;
    }
    
    inline Boolean Atomic::CompareSwap2(Int64 volatile* address, Int64 oldValue, Int64 newValue) {
        if (*address == oldValue) {
            *address = newValue;
            return true;
        }
        
        return false;
    }

    inline Boolean Atomic::CompareSwap2(UInt64 volatile* address, UInt64 oldValue, UInt64 newValue) {
        if (*address == oldValue) {
            *address = newValue;
            return true;
        }
        
        return false;
    }
    
    inline Boolean Atomic::CompareSwap2(void* volatile* address, void* oldValue, void* newValue) {
        if (*address == oldValue) {
            *address = newValue;
            return true;
        }
        
        return false;     
    }
}

#endif // RS_PORTABILITY_GENERIC_ATOMIC_IPP